package com.youaishujuhui.devops.web.util.syslog;

import java.lang.reflect.Method;

import javax.servlet.http.HttpServletRequest;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.nutz.lang.Strings;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import com.youaishujuhui.devops.web.domain.manage.SysAuditLog;
import com.youaishujuhui.devops.web.domain.manage.SysUser;
import com.youaishujuhui.devops.web.service.manage.SysAuditLogService;
import com.youaishujuhui.devops.web.util.Common;
import com.youaishujuhui.devops.web.vo.Result;

import cn.hutool.core.exceptions.ExceptionUtil;

@Aspect
@Component 
public class SystemLogAopAction {

	@Autowired
	private SysAuditLogService logService;

	// 配置接入点,如果不知道怎么配置,可以百度一下规则
	@Pointcut("execution(* com.youaishujuhui.devops.web.controller..*.*(..))")
	private void controllerAspect() {
	}// 定义一个切入点

	@Around("controllerAspect()")
	public Object around(ProceedingJoinPoint pjp) throws Throwable {

		// 拦截的实体类，就是当前正在执行的controller
		Object target = pjp.getTarget();
		
		// 拦截的方法名称。当前正在执行的方法
		String methodName = pjp.getSignature().getName();
		
		// 拦截的方法参数
		Object[] args = pjp.getArgs();
		
		// 拦截的放参数类型
		Signature sig = pjp.getSignature();
		MethodSignature msig = null;
		
		if (!(sig instanceof MethodSignature)) {
			throw new IllegalArgumentException("该注解只能用于方法");
		}
		
		msig = (MethodSignature) sig;

		Object object = null;
		// 获得被拦截的方法
		Method method = null;
		try {
			method = target.getClass().getMethod(methodName, msig.getMethod().getParameterTypes());
		} catch (NoSuchMethodException e1) {
			e1.printStackTrace();
		} catch (SecurityException e1) {
			e1.printStackTrace();
		}

		if (null != method) {
			// 判断是否包含自定义的注解，说明一下这里的SystemLog就是我自己自定义的注解
			if (method.isAnnotationPresent(SystemLog.class)) {
				SysAuditLog log = new SysAuditLog();

				// 获取登录用户账户
				HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes())
						.getRequest();

				SysUser sysUser = (SysUser) request.getSession().getAttribute(Common.SESSION_LOGIN_USER_KEY);

				if (sysUser == null) {
					return pjp.proceed();
				}

				log.setUserName(sysUser.getUserName());
				
				SystemLog systemlog = method.getAnnotation(SystemLog.class);
				
				log.setModule(systemlog.module());
				log.setOper(systemlog.oper());

				if (args != null) {
					String argsStr = Strings.join(",", args);
					log.setArgs(argsStr);
				}

				try {
					object = pjp.proceed();
					
					if (object instanceof Result) {
						Result<?> result = (Result<?>) object;
						if (result.getCode() == Result.SUCCESS) {
							log.setSuc(true);
						} else {
							log.setSuc(false);
							log.setError(result.getMsg());
						}
					}

					// 日志入库
					logService._insert(log);
				} catch (Throwable e) {
					// 如控制器发生异常会执行此处
					log.setSuc(false);
					log.setError(ExceptionUtil.stacktraceToString(e));
					// 日志入库
					logService._insert(log);
					
					throw e;
				}
			} else {
				// 没有包含注解则放行
				object = pjp.proceed();
			}
		} else {
			// 不需要拦截直接放行
			object = pjp.proceed();
		}
		return object;
	}
}